<?php

class ColorCalc {
	protected $aColors;
	
	public function __construct() {
		$this->aColors = array();
		$this->aColors ['STARTCOLOR']	= array('RED' => 255, 'GREEN' => 0,   'BLUE' => 0 );
		$this->aColors ['MIDCOLOR']	= array('RED' => 238, 'GREEN' => 136, 'BLUE' => 17);
		$this->aColors ['ENDCOLOR']	= array('RED' => 0,   'GREEN' => 170, 'BLUE' => 0 );
	}

	public function getRGBCalc($pct) {
		$r1 = 0;
		$r2 = 0;
		$g1 = 0;
		$g2 = 0;
		$b1 = 0;
		$b2 = 0;
		$calcRed = 0;
		$calcGreen = 0;
		$calcBlue = 0;
	 
		# Sanitize the percent is '0 <= pct <= 100'
		$this->cleanPctRange($pct);
		//$pct = $pct < 0 ? 0 : $pct;
		//$pct = $pct > 100 ? 100 : $pct;
		
		# Going from start color to mid color
		if( $pct <= 50 ) {
			$pct *= 2;
			$r1 = $this->aColors['STARTCOLOR']['RED'];		$r2 = $this->aColors['MIDCOLOR']['RED'];
			$g1 = $this->aColors['STARTCOLOR']['GREEN'];		$g2 = $this->aColors['MIDCOLOR']['GREEN'];
			$b1 = $this->aColors['STARTCOLOR']['BLUE'];		$b2 = $this->aColors['MIDCOLOR']['BLUE'];
		} 
	
		# Going from Midcolor to endcolor
		else {
			$pct -= (100-$pct);
			$r1 = $this->aColors['MIDCOLOR']['RED'];		$r2 = $this->aColors['ENDCOLOR']['RED'];
			$g1 = $this->aColors['MIDCOLOR']['GREEN'];		$g2 = $this->aColors['ENDCOLOR']['GREEN'];
			$b1 = $this->aColors['MIDCOLOR']['BLUE'];		$b2 = $this->aColors['ENDCOLOR']['BLUE'];
		}
		
		# Crunch the numbers
		if( $r1 < $r2 )	{ $calcRed	= floor($r1 + (($r2-$r1)*($pct/100))); }
		else		{ $calcRed	= floor($r1 - (($r1-$r2)*($pct/100))); }

		if( $g1 < $g2 )	{ $calcGreen	= floor($g1 + (($g2-$g1)*($pct/100))); }
		else		{ $calcGreen	= floor($g1 - (($g1-$g2)*($pct/100))); }

		if( $b1 < $b2 ) { $calcBlue	= floor($b1 + (($b2-$b1)*($pct/100))); }
		else		{ $calcBlue	= floor($b1 - (($b1-$b2)*($pct/100))); }
		
		return "$calcRed, $calcGreen, $calcBlue";
	}
	
	protected function cleanPctRange(&$pct) {
		$pct = $pct < 0 ? 0 : $pct;
		$pct = $pct > 100 ? 100 : $pct;	
	}

	public function setStartColor($r,$g,$b) {
		$this->aColors['STARTCOLOR']['RED']	= $r;
		$this->aColors['STARTCOLOR']['GREEN']	= $g;
		$this->aColors['STARTCOLOR']['BLUE']	= $b;
	}

	public function setMidColor($r,$g,$b) {
		$this->aColors['MIDCOLOR']['RED']	= $r;
		$this->aColors['MIDCOLOR']['GREEN']	= $g;
		$this->aColors['MIDCOLOR']['BLUE']	= $b;
	}

	public function setEndColor($r,$g,$b) {
		$this->aColors['ENDCOLOR']['RED']	= $r;
		$this->aColors['ENDCOLOR']['GREEN']	= $g;
		$this->aColors['ENDCOLOR']['BLUE']	= $b;
	}
	
	public function dump() {
		return	"START:{$this->aColors['STARTCOLOR']['RED']},{$this->aColors['STARTCOLOR']['GREEN']},{$this->aColors['STARTCOLOR']['BLUE']}\n".
			"MID:{$this->aColors['MIDCOLOR']['RED']},{$this->aColors['MIDCOLOR']['GREEN']},{$this->aColors['MIDCOLOR']['BLUE']}\n".
			"END:{$this->aColors['ENDCOLOR']['RED']},{$this->aColors['ENDCOLOR']['GREEN']},{$this->aColors['ENDCOLOR']['BLUE']}\n";
	}

	public function dumpHTML() {
		for($i=0; $i<=100; $i++) {
			$returnVal .= "<span style=\"background-color:rgb(".$this->getRGBCalc($i).");\">&nbsp;</span>";
		}
		return	"<span style=\"border:solid black 1px;\">$returnVal</span>";
	}

}

class ColorGraph extends ColorCalc {
	var $_useColorPercents;
	var $_showPercents;
	var $_showTotals;
	var $_textClass;
	var $_canExceed100Pct;

	public function __construct() {
		ColorCalc::__construct();
		$this->_useColorPercents=true;
		$this->_showPercents=true;
		$this->_showTotals=true;
		$this->_textClass='';
		$this->_canExceed100Pct=true;
	}
	
	public function getHorrizBar($count, $total) {
		# Calculate percent
		$pct = !$total || $total==0
			? 0.00 
			: floor(($count*100)/$total);
		
		#Check for and correct >100%
		$displayPct = $pct;
		ColorCalc::cleanPctRange($pct);
		if( ! $this->_canExceed100Pct ) {
			$displayPct = $pct;
		}
		# Make colors for percent and graph
		$pctColor = "rgb(" . ColorCalc::getRGBCalc($pct) . ")";
		$progressBox = "
			<div style=\"border:solid black 1px;background-color:#fff;\" width=\"100px\" >
			<div style=\"height:12px;border:solid $pctColor 1px; background-color:$pctColor;width:$pct%;font-weight:bold;color:white;\"></div>
			<div>
		";
		
		if( $this->_showPercents ) {
			$colorPercents = 
				$this->_useColorPercents
				? "color:$pctColor;"
				: "";
				
			$dispPct = "<td width=\"35\" align=\"right\"><span class=\"{$this->_textClass}\"><span style=\"$colorPercents\">$displayPct</span>%</span></td>";
		}
		
		if( $this->_showTotals ) {
			$dispTotals = "<td align=\"left\"><span class=\"{$this->_textClass}\">($count/$total)</span></td>";
		}

		return "<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\">
			 <tr>
			  $dispPct
			  <td width=\"150\" align=\"left\">$progressBox</td>
			  $dispTotals
			 </tr>
			</table>
		";
	}
	
	// Set class to use for display text
	public function setTextClass($class)  { 
		$this->_textClass = $class; 
	}
	
	// Show the percentages
	public function showPercents()  { 
		$this->_showPercents = true; 
	}
	// Hide the percentages
	public function hidePercents() { 
		$this->_showPercents = false; 
	}
	
	// Show the totals
	public function showTotals()  { 
		$this->_showTotals = true; 
	}
	// Hide the totals
	public function hideTotals() { 
		$this->_showTotals = false; 
	}

	// Color the percentages
	public function colorPercentsOn()  { 
		$this->_useColorPercents = true; 
	}
	// Don't color the percentages
	public function colorPercentsOff() { 
		$this->_useColorPercents = false; 
	}
}

/*************************************************************************
<Header> 
 <Title>         C_colorcycle.inc          </Title>
..........................................................................
 <Description>
      This defines an object which provides automatically alternating
       colors with each successive call to the getColor() method. By
       default it returns white and light-green, good for alternating
       row color in an html report.
 </Description>
......................................................................
 <Author>Damien DeZurik</Author>
 <Date>2009-08-26</Date>
......................................................................
 <License version='open'>
      This code may be used in its current form or modified as much
       as desired by anyone responsible for anything using it.
 </License>
......................................................................
 <Notes>

 </Notes>
......................................................................
 <Usage>
	// -----------
	// Example 1 - Declere an instance with default white and light green color cycle.
	$obj_lineColor = new ColorCycle();
	
	// Now simply call the getColor() method to cycle through colors;

	while( $r = getDatabaseRows() ) {
		print "<tr bgcolor=\"" . $obj_lineColor->getColor() . "\"><td>$r[2]</td></tr>";
	}
	// -----------
	// Example 2 - Initialize with an array of custom colors.
	$cc = new ColorCycle(array("#FF0000","#FFFFFF","#0000FF"));

	// -----------
	// Example 3 - Sticky color changing only when stick field changes.
	$cc = new ColorCycle();
	while( $r = pg_fetch_array($pgo->res) ) {
		// getStickyColor will only return the next color in the cycle when
		//  $r[0] has changed to something new.
		$blockColor = $cc->getStickyColor($r[0]);

		// getStickyFieldIfChanged returns the value of the sticky field the first
		//  time it is called after the field has changed. If the value of the field
		//  has not changed since the last call, it returns a blank string. This gives
		//  the effect illistrated below where a column that repeats the same value
		//  ("department 20") does not repeat the same value row after row and, instead,
		//  only shows the value the first time it is encountered then blanks for successive
		//  rows until the value changes.  Used in combination with getStickyColor nicely
		//  colors all the rows with the same sticky field in the same color.  When the
		//  sticky field changes, so does the background color.  See example below.
		//  +---------------+------+
		//  | department 20 | $15k |  // background color is light green
		//  +---------------+------+
		//  |               |  $2k |  // background color is light green
		//  +---------------+------+
		//  | department 99 | $31k |  // background color is white
		//  +---------------+------+

		print "<span style=\"color:$blockColor;\">".print $cc->getStickyFieldIfChanged()."</span>";
		print "<span style=\"color:$blockColor;\">$r[1]</span>";
	}
 </Usage>
......................................................................
 <Changelog />
 </Changelog>
</Header>
********************************************************************/

Class ColorCycle {
	// Member variables.
	var $colorArrIndex;
	var $colors=array();
	var $stickyFlagLast;
	var $stickyFlagCurrent;
	var $stickyFlagChanged;

	var $LTGREEN="#EEFFEE";
	var $LTGREY="#EEEEEE";
	var $WHITE="#FFFFFF";

	// Cstr
	function ColorCycle($colorArr="")
	{
		if( empty($colorArr) )
			$colorArr = array($this->LTGREEN,$this->WHITE);

		// Start here because getColor() increments first.
		$this->colorArrIndex = -1;

		// Just set colors array to incoming array of colors
		$this->colors = $colorArr;

		// Keeps track of last flag value so getStickyColor($flag) knows
		//  when to change color.  Initialized to a string that is
		// Unlikely to be encountered.
		$this->stickyFlagLast = "|:|";

		// Current sticky field value
		$this->stickyFlagCurrent = "|:|";

		// So client knows when flag field has changed.
		$this->stickyFlagChanged = false;
	}

	// Member functions
	// set colors using array
	function setColors($colorArr)
	{
		$this->colors = $colorArr;
	}

	function getColor()
	{
		$this->colorArrIndex++;

		// Reset to 0 after arraysize exceeded.
		if( $this->colorArrIndex > (count($this->colors) - 1) )
			$this->colorArrIndex = 0;

		return $this->colors[$this->colorArrIndex];
	}

	// When called with a flag field, only alternates color when the field
	//  has changed.
	function getStickyColor($flag)
	{
		$this->stickyFlagCurrent = $flag;
		// If flag has changed, switch color
		if( $this->stickyFlagCurrent != $this->stickyFlagLast ) {
			$this->colorArrIndex++;
			$this->stickyFlagChanged = true;

			// Reset to 0 after arraysize exceeded.
			if( $this->colorArrIndex > (count($this->colors) - 1) )
				$this->colorArrIndex = 0;
		}
		else
			$this->stickyFlagChanged = false;

		$this->stickyFlagLast = $this->stickyFlagCurrent;

		return $this->colors[$this->colorArrIndex];
	}

	function getStickyFieldIfChanged()
	{
		if( $this->stickyFlagChanged )
			return $this->stickyFlagCurrent;
		else
			return "";
	}
}

?>